package com.boco.pciv.service.sys.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Editor;
import com.boco.pciv.SysProperties;
import com.boco.pciv.core.entity.BizTree;
import com.boco.pciv.core.entity.Constants;
import com.boco.pciv.core.entity.SelectItem;
import com.boco.pciv.core.exception.PcivException;
import com.boco.pciv.core.util.SearchUtil;
import com.boco.pciv.entity.sys.ResTree;
import com.boco.pciv.mapper.sys.IRoleMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.boco.pciv.core.service.PcivBaseServiceImpl;

import java.util.*;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.hutool.core.util.StrUtil;

import com.boco.pciv.mapper.sys.IResMapper;
import com.boco.pciv.entity.sys.ResInfo;
import com.boco.pciv.service.sys.IResService;


@Service
public class ResServiceImpl extends PcivBaseServiceImpl<IResMapper,ResInfo,String> implements IResService {
    //logger
    private static final Logger logger = LoggerFactory.getLogger(ResServiceImpl.class);
    @Autowired
    private IRoleMapper roleMapper;
    @Autowired
    SysProperties sysProp;
    @Autowired
    IResService self;

    @Cacheable(value = "res")
    @Override
    public List<ResInfo> getAll() {
        List<ResInfo> list = mapper.queryList(new HashMap<>());
        for(ResInfo item:list){
            final String pid = item.getParentId();
            if(pid.equals(Constants.ModulesParentID)){
                item.setParentName(Constants.ModulesParentName);
            }
            else{
                List<ResInfo> infos = list.stream().filter(s -> s.getId().equalsIgnoreCase(pid))
                        .collect(Collectors.toList());
                if (infos!=null &&infos.size()>0){
                    item.setParentName(infos.get(0).getName());
                }
//                ResInfo parentDict = CollectionUtil.findOneByField(list, "id", pid);
//                if (parentDict!= null){
//                    item.setParentName(parentDict.getName());
//                }
            }
        }
        return list;
    }

    @Override
    public List<ResInfo> getListByUser(String userId) {
        return mapper.queryListByUser(userId);
    }

    @Override
    public List<ResInfo> getListByRole(String roleId) {
        return mapper.queryListByRole(roleId);
    }

    @Override
    public ResTree getResTreeByUser(String userid) {
        List<ResInfo> list = getListByUser(userid);
        ResTree tree = new ResTree();
        tree.setId(Constants.ModulesParentID);
        tree.setName(Constants.ModulesParentName);
        tree.setLevelId(0);
        tree.setChildren(AddChildRes(tree,list));
        return  tree;
    }

    @Override
    public ResTree getResTreeByRole(String roleId) {
        List<ResInfo> list = self.getListByRole(roleId);
        ResTree tree = new ResTree();
        tree.setId(Constants.ModulesParentID);
        tree.setName(Constants.ModulesParentName);
        tree.setLevelId(0);
        tree.setChildren(AddChildRes(tree,list));
        return  tree;
    }

    @Override
    public ResTree getResTreeByParent(String parentId) {
        return getResTreeByUserAndParent(null,parentId);
    }

    @Override
    @Cacheable(value = "res",key = "#id")
    public ResInfo getOne(String id) {
        return super.getOne(id);
    }

    @Override
    @Cacheable(value = "userRes")
    public ResTree getResTreeByUserAndParent(String userId, String parentId) {
        ResTree tree = new ResTree();

        ResInfo root;
        if(StrUtil.isBlank(parentId) || Constants.ModulesParentID.equals(parentId)){
            tree.setId(Constants.ModulesParentID);
            tree.setName(Constants.ModulesParentName);
            tree.setLevelId(0);
        }
        else{
            root = self.getOne(parentId);
            if(root!=null) {
                tree.setId(root.getId());
                tree.setName(root.getName());
                tree.setLevelId(root.getLevelId());
                tree.setParentId(root.getParentId());
            }
        }

        List<ResInfo> list ;
        if (StrUtil.isBlank(userId)){
            list = self.getAll();
        }
        else {
            list = getListByUser(userId);
        }
        tree.setChildren(AddChildRes(tree,list));
        //默认展开第一个
        if (tree.getChildren()!=null && tree.getChildren().size()>0){
            tree.getChildren().get(0).setSpread(true);
        }
        return tree;
    }

//    @Override
    public BizTree getEasyUITreeByParent(String parentId) {
        BizTree tree = new BizTree();

        ResInfo root;
        if(StrUtil.isBlank(parentId) || Constants.ModulesParentID.equals(parentId)){
            tree.setId(Constants.ModulesParentID);
            tree.setName(Constants.ModulesParentName);
        }
        else{
            root = self.getOne(parentId);
            if(root!=null) {
                tree.setId(root.getId());
                tree.setName(root.getName());
            }
        }

        List<ResInfo> list = self.getAll();
        tree.setChildren(AddChildRes(tree,list));

        return tree;
    }

    @Override
    public List<SelectItem> getResTreeByParent4Select(String parentId) {
        BizTree tree = getEasyUITreeByParent(parentId);
        String deptItemType = "ResTreeList";
        return SearchUtil.EasyTree2TreeList(tree,deptItemType);
    }

    @Override
    public List<String> getResIdByRole(String roleId) {
        return mapper.queryIdListByRole(roleId);
    }

    @Override
    public List<ResInfo> getMenuListByUser(String userId) {
         return mapper.queryListByUserLevelOne(userId);
    }

    @Override
    @CacheEvict(value = "res",allEntries=true)
    public void add(ResInfo entity) {
        if (entity==null){
            throw  new PcivException("新增数据不能为空");
        }
        String resId = entity.getId();
        if (StrUtil.isEmpty(resId)) {
            resId = UUID.randomUUID().toString();
            entity.setId(resId);
        }
        entity.setLevelId(getLevelId(entity));
        entity.setState(1);
        mapper.insert(entity);

        //默认增加权限给管理员
        Map<String, String> reMap = new HashMap<String, String>();
        reMap.put("resId", resId);
        reMap.put("roleId", Constants.SysAdminRoleId);
        roleMapper.insertRoleRes(reMap);
    }

    @Override
    @CacheEvict(value = "res",allEntries=true)
    public Integer edit(ResInfo entity) {
        entity.setLevelId(getLevelId(entity));
        entity.setState(1);
        return mapper.update(entity);
    }

    @Override
    @CacheEvict(value = "res",allEntries=true)
    public void delete(String id) {
        super.delete(id);
        //默认删除无效资源关系
        roleMapper.deleteRoleResByResId(id);
    }

    private Integer getLevelId(ResInfo info){
        //设置级别
        String pid = info.getParentId();
        if (StrUtil.isBlank(pid)) {
            return 1;
        }
        else{
            ResInfo p = getOne(pid);
            if (p!=null){
                Integer plevelId= p.getLevelId();
                if(plevelId!= null) {
                    return p.getLevelId() + 1;
                }
            }
        }
        return 1;
    }

    /*递归创建资源树*/
    private  List<ResTree> AddChildRes(final ResTree curNode, List<ResInfo> AllSource) {
        Collection<ResInfo> childLst = CollectionUtil.filter(AllSource, new Editor<ResInfo>() {
            @Override
            public ResInfo edit(ResInfo info) {
                if (info.getParentId().equals(curNode.getId())) {
                    return info;
                } else {
                    return null;
                }
            }
        });

        CollectionUtil.sort(childLst,new Comparator<ResInfo>() {
            @Override
            public int compare(ResInfo o1, ResInfo o2) {
                return o1.getRank() >o2.getRank() ? 1:0;
            }
        });

        List<ResTree> childResourceTree = new ArrayList<ResTree>();
        for (ResInfo item:childLst) {
            ResTree cur = new ResTree();
            cur.setId(item.getId());
            cur.setName(item.getName());
            cur.setParentId(item.getParentId());
            cur.setLevelId(item.getLevelId());
            cur.setRank(item.getRank());
            cur.setType(item.getType());
            cur.setUrl(item.getUrl());
            cur.setIcon(item.getIcon());
            cur.setChildren(AddChildRes(cur,AllSource));
            childResourceTree.add(cur);
        }
        return childResourceTree;
    }

    private  List<BizTree> AddChildRes(final BizTree curNode, List<ResInfo> AllSource) {
        Collection<ResInfo> childLst = CollectionUtil.filter(AllSource, new Editor<ResInfo>() {
            @Override
            public ResInfo edit(ResInfo info) {
                if (info.getParentId().equals(curNode.getId())) {
                    return info;
                } else {
                    return null;
                }
            }
        });

        CollectionUtil.sort(childLst, new Comparator<ResInfo>() {
            @Override
            public int compare(ResInfo o1, ResInfo o2) {
                return o1.getRank() >o2.getRank() ? 1:0;
            }
        });
        List<BizTree> childResourceTree = new ArrayList<BizTree>();
        for (ResInfo item:childLst) {
            BizTree cur = new BizTree();
            cur.setId(item.getId());
            cur.setName(item.getName());
            cur.setChildren(AddChildRes(cur,AllSource));
            childResourceTree.add(cur);
        }
        return childResourceTree;
    }
}
